﻿#region Using directives

using System;
using System.Collections.Generic;
using System.Text;

using Weazel.NativeMath;

using Microsoft.VisualStudio.TestTools.UnitTesting;

#endregion


namespace Weazel.NativeMath.Test
{
	[TestClass]
	public class TestAddition
	{
		/**************************************************************************
		 * Addition (Signed)
		 **************************************************************************/
		[TestMethod]
		public void TestAddition_1()
		{
			Integer a = new Integer(32, 100, false);
			Integer b = new Integer(32, 125, false);
			Integer r = a + b;

			Assert.IsFalse(r.Signed);
			Assert.AreEqual(32, r.Width);
			Assert.AreEqual("225", r.ToDecimalString());

			r = new Integer(32, false);
			Integer.Add(r, a, b);

			Assert.IsFalse(r.Signed);
			Assert.AreEqual(32, r.Width);
			Assert.AreEqual("225", r.ToDecimalString());
		}

		[TestMethod]
		public void TestAddition_2()
		{
			Integer a = new Integer(32, 100, true);
			Integer b = new Integer(32, 125, false);
			Integer r = a + b;

			Assert.IsTrue(r.Signed);
			Assert.AreEqual(32, r.Width);
			Assert.AreEqual("225", r.ToDecimalString());

			r = new Integer(32, false);
			Integer.Add(r, a, b);

			Assert.IsFalse(r.Signed);
			Assert.AreEqual(32, r.Width);
			Assert.AreEqual("225", r.ToDecimalString());
		}

		/**************************************************************************
		 * Addition (Signed)
		 **************************************************************************/
		[TestMethod]
		public void TestAddition_FirstInputGreaterThanSecond_VaryingResultWidth_1()
		{
			Integer a = new Integer(64, "0xFFFFFFFFFFFFFFFF", false);
			Integer b = new Integer(32, 2, false);
			Integer r = a + b;

			// using the overloaded operator ..
			Assert.IsFalse(r.Signed);
			Assert.AreEqual(64, r.Width);
			Assert.AreEqual("1", r.ToHexadecimalString()); // result has been truncated

			// user defined result ..
			r = new Integer(96, false);
			Integer.Add(r, a, b);

			Assert.IsFalse(r.Signed);
			Assert.AreEqual(96, r.Width);
			Assert.AreEqual("10000000000000001", r.ToHexadecimalString());
		}

		[TestMethod]
		public void TestAddition_FirstInputGreaterThanSecond_VaryingResultWidth_2()
		{
			Integer a = new Integer(96, "0xFFFFFFFFFFFFFFFF", false);
			Integer b = new Integer(64, 2, false);
			Integer r = a + b;

			// using the overloaded operator ..
			Assert.IsFalse(r.Signed);
			Assert.AreEqual(96, r.Width);
			Assert.AreEqual("10000000000000001", r.ToHexadecimalString());

			// user defined result ..
			r = new Integer(32, false);
			Integer.Add(r, a, b);

			Assert.IsFalse(r.Signed);
			Assert.AreEqual(32, r.Width);
			Assert.AreEqual("1", r.ToHexadecimalString()); // result truncated
		}

		[TestMethod]
		public void TestAddition_FirstInputGreaterThanSecond_VaryingResultWidth_3()
		{
			Integer a = new Integer(96, "0xFFFFFFFFFFFFFFFF", false);
			Integer b = new Integer(32, 2, false);
			Integer r = a + b;

			// using the overloaded operator ..
			Assert.IsFalse(r.Signed);
			Assert.AreEqual(96, r.Width);
			Assert.AreEqual("10000000000000001", r.ToHexadecimalString());

			// user defined result ..
			r = new Integer(64, false);
			Integer.Add(r, a, b);

			Assert.IsFalse(r.Signed);
			Assert.AreEqual(64, r.Width);
			Assert.AreEqual("1", r.ToHexadecimalString()); // result truncated
		}

		[TestMethod]
		public void TestAddition_FirstInputLessThanSecond_VaryingResultWidth_1()
		{
			Integer a = new Integer(32, "0xFFFFFFFF", false);
			Integer b = new Integer(64, 2, false);
			Integer r = a + b;

			// using the overloaded operator ..
			Assert.IsFalse(r.Signed);
			Assert.AreEqual(64, r.Width);
			Assert.AreEqual("100000001", r.ToHexadecimalString()); // result truncated

			// user defined result ..
			r = new Integer(96, false);
			Integer.Add(r, a, b);

			Assert.IsFalse(r.Signed);
			Assert.AreEqual(96, r.Width);
			Assert.AreEqual("100000001", r.ToHexadecimalString());
		}

		[TestMethod]
		public void TestAddition_FirstInputLessThanSecond_VaryingResultWidth_2()
		{
			Integer a = new Integer(32, "0xFFFFFFFF", false);
			Integer b = new Integer(96, 2, false);
			Integer r = a + b;

			// using the overloaded operator ..
			Assert.IsFalse(r.Signed);
			Assert.AreEqual(96, r.Width);
			Assert.AreEqual("100000001", r.ToHexadecimalString());

			// user defined result ..
			r = new Integer(64, false);
			Integer.Add(r, a, b);

			Assert.IsFalse(r.Signed);
			Assert.AreEqual(64, r.Width);
			Assert.AreEqual("100000001", r.ToHexadecimalString());
		}

		[TestMethod]
		public void TestAddition_FirstInputLessThanSecond_VaryingResultWidth_3()
		{
			Integer a = new Integer(64, "0xFFFFFFFFFFFFFFFF", false);
			Integer b = new Integer(96, 2, false);
			Integer r = a + b;

			// using the overloaded operator ..
			Assert.IsFalse(r.Signed);
			Assert.AreEqual(96, r.Width);
			Assert.AreEqual("10000000000000001", r.ToHexadecimalString());

			// user defined result ..
			r = new Integer(32, false);
			Integer.Add(r, a, b);

			Assert.IsFalse(r.Signed);
			Assert.AreEqual(32, r.Width);
			Assert.AreEqual("1", r.ToHexadecimalString()); // result truncated
		}

		[TestMethod]
		public void TestAddition_SingleBit()
		{
			Integer a = new Integer(1, false);
			Integer b = new Integer(1, false);

			a.Assign(0);
			b.Assign(0);

			Integer r = a + b;

			Assert.AreEqual("0", r.ToDecimalString());
			Assert.AreEqual(1, r.Width);

			a.Assign(0);
			b.Assign(1);

			r = a + b;

			Assert.AreEqual("1", r.ToDecimalString());
			Assert.AreEqual(1, r.Width);

			a.Assign(1);
			b.Assign(1);

			r = a + b;

			Assert.AreEqual("0", r.ToDecimalString());
			Assert.AreEqual(1, r.Width);
		}
	}
}
